package com.server.core.domain;

import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.cookie.Cookie;
import io.netty.handler.codec.http.cookie.ServerCookieDecoder;
import io.netty.handler.codec.http.multipart.*;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Request {

    private  FullHttpRequest request;
    private  Map<String, String> headers = new HashMap<>();
    private  Map<String, Object> params = new HashMap<>();
    private  Map<String, Cookie> cookies = new HashMap<>();
    private static final HttpDataFactory HTTP_DATA_FACTORY = new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE);
    private String ip ;

    public Request(ChannelHandlerContext ctx, FullHttpRequest request) {
        this.request =  request;
        //存储headers与cookies
        putHeadersAndCookies(request.headers());
        //处理uri中的参数（GET,PUT）
        putParams(new QueryStringDecoder(request.uri()));
        if(request.method() == HttpMethod.POST) {
            HttpPostRequestDecoder decoder = null;
            try {
                decoder = new HttpPostRequestDecoder(HTTP_DATA_FACTORY, this.request);
                this.putParams(decoder);
            } finally {
                if(null != decoder){
                    decoder.destroy();
                    decoder = null;
                }
            }
        }
        // IP
        this.putIp(ctx);
    }

    public String getUri() {
         String uri = request.uri();
         return uri;
    }

    public HttpMethod getMethod() {
        /**
         * @desc 配置rest风格的 get post delete put
         */
        HttpMethod method = request.method();

        switch (method.toString()) {
            case "GET":
                return HttpMethod.GET;
            case "POST" :
                String _method = this.getParams().get("_method") + "";
                if(_method.equals("null")) {
                    return HttpMethod.POST;
                }
                if("PUT".equals(_method)) {
                    return HttpMethod.PUT;
                }
                if("DELETE".equals(_method)) {
                    return HttpMethod.POST;
                }
                System.out.println(_method);
                break;
        }
         return  null;
    }
    public FullHttpRequest getRequest() {
        return request;
    }

    public void setRequest(FullHttpRequest request) {
        this.request = request;
    }

    public Map<String, String> getHeaders() {
        return headers;
    }

    public void setHeaders(Map<String, String> headers) {
        this.headers = headers;
    }

    public Map<String, Object> getParams() {
        return params;
    }

    public void setParams(Map<String, Object> params) {
        this.params = params;
    }

    public Map<String, Cookie> getCookies() {
        return cookies;
    }

    public void setCookies(Map<String, Cookie> cookies) {
        this.cookies = cookies;
    }

    public Cookie getCookie(String key) {
         return cookies.get(key);
    }
    /**
     * 填充头部信息和Cookie信息
     *
     * @param headers HttpHeaders
     */
    protected void putHeadersAndCookies(HttpHeaders headers) {
        for (Map.Entry<String, String> entry : headers) {
            this.headers.put(entry.getKey(), entry.getValue());
        }

        // Cookie
        final String cookieString = this.headers.get("Cookie");
        if (cookieString!=null) {
            final Set<Cookie> cookies = ServerCookieDecoder.LAX.decode(cookieString);
            for (Cookie cookie : cookies) {

                this.cookies.put(cookie.name(), cookie);
            }
        }
    }

    /**
     * 获取get中的参数
     * @param decoder
     */
     public void putParams(QueryStringDecoder decoder) {
          if(decoder==null) {
              return;
          }
          List<String> valueList;
          for(Map.Entry<String, List<String>> entry : decoder.parameters().entrySet()) {
              valueList = entry.getValue();
              if(null != valueList){
                  this.putParam(entry.getKey(), 1 == valueList.size() ? valueList.get(0) : valueList);
              }
          }
     }
    /**
     * 填充参数（POST请求的参数）
     *
     * @param decoder QueryStringDecoder
     */
    protected void putParams(HttpPostRequestDecoder decoder) {
        if (null == decoder) {
            return;
        }

        for (InterfaceHttpData data : decoder.getBodyHttpDatas()) {
            putParam(data);
        }
    }
    public String getHeader(String key) {
        return headers.get(key);
    }

    protected void putParam(InterfaceHttpData data) {
         InterfaceHttpData.HttpDataType dataType = data.getHttpDataType();
         if(dataType == InterfaceHttpData.HttpDataType.FileUpload) {
             FileUpload fileUpload = (FileUpload)data;
             if(fileUpload.isCompleted()) {
                try{
                    this.putParam(data.getName(), fileUpload.getFile());
                }catch (IOException e) {
                 //   logger.info(e.getMessage());
                }
             }
         }
    }

    public void  putParam(String key, Object val) {
            this.params.put(key, val);
    }

    public void putIp(ChannelHandlerContext ctx) {
        ///优先使用这个head表示的ip，因为现在的web服务广泛的使用了nginx代理，因此只有header里的才能保证数据来源
         String ip = getHeader("X-Forwarded-For");
         if(ip == null) {
           ip = ((InetSocketAddress)ctx.channel().remoteAddress()).getAddress().getHostAddress();
          }
         this.ip = ip;
    }

}
